package br.com.faculdade.application.controller;

import br.com.faculdade.domain.service.ReservaHospedagemService;
import br.com.faculdade.infrastructure.entity.Apartamento;
import br.com.faculdade.infrastructure.entity.Hospede;
import br.com.faculdade.infrastructure.entity.Lancamento;
import br.com.faculdade.infrastructure.entity.ReservaEstadia;
import br.com.faculdade.infrastructure.entity.TipoApartamento;
import java.util.Date;
import java.util.List;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.End;
import org.jboss.seam.annotations.FlushModeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.datamodel.DataModel;
import org.jboss.seam.annotations.datamodel.DataModelSelection;
import org.jboss.seam.log.Log;

/**
 *
 * @author Kirmaier
 */
@Scope(ScopeType.SESSION)
@Name("reservaHospedagemAction")
public class ReservaHospedagemController extends BaseController {

    @Logger
    private Log log;
    //Injeção dos services
    @In
    private ReservaHospedagemService reservaHospedagemService;
    private ReservaEstadia reserva;
    @DataModel("reservas")
    private List<ReservaEstadia> reservasDM;
    @DataModelSelection
    private ReservaEstadia reservaSelecionada;
    private Apartamento apartamento;
    private Lancamento lancamento;
    private List<Hospede> hospedes;
    private List<Apartamento> apartamentos;
    private List<TipoApartamento> tiposApartamento;
    private Operacao operacaoAtual;
    private Integer tipoApartamento;
    private Integer apartamentoSelecionado;
    private Integer hospedeSelecionado;
    private Float valor;
    private Date paramDataMarcacao;
    private Date paramDataChegada;
    private Short paramStatusReserva;
    private Integer paramTipoApartamento;
    private String paramHospede;
    private static final String RESERVA = "reserva";
    private static final String CADASTRO_ALTERAR = "criar_alterar_reserva";

    @Create
    public String setup() {
        reservasDM = null;

        tiposApartamento = reservaHospedagemService.obterTodosTipos();

        apartamento = null;

        paramDataMarcacao = null;
        paramDataChegada = null;
        paramStatusReserva = null;
        paramTipoApartamento = null;
        paramHospede = null;

        tipoApartamento = null;
        apartamentoSelecionado = null;
        hospedeSelecionado = null;


        return RESERVA;
    }

    @Begin(join = true)
    public String criarSetup() {
        operacaoAtual = Operacao.CRIACAO;

        reserva = reservaHospedagemService.criar();
        Short hospedado = 2;
        reserva.setReserva(hospedado);

        hospedes = reservaHospedagemService.obterTodosHospedes();

        apartamento = null;

        tipoApartamento = null;
        apartamentoSelecionado = null;
        hospedeSelecionado = null;

        return CADASTRO_ALTERAR;
    }

    @Begin(join = true)
    public String criarReservaSetup() {
        operacaoAtual = Operacao.CRIACAO;

        reserva = reservaHospedagemService.criar();
        Short hospedado = 1;
        reserva.setReserva(hospedado);

        hospedes = reservaHospedagemService.obterTodosHospedes();

        apartamento = null;

        tipoApartamento = null;
        apartamentoSelecionado = null;
        hospedeSelecionado = null;

        return CADASTRO_ALTERAR;
    }

    @End
    public String criar() {
        try {
            reservaHospedagemService.salvar(reserva, hospedeSelecionado, apartamentoSelecionado);

            adicionarMensagemInformacao("msgReservaCriarSucesso");

            pesquisar();

            return RESERVA;
        } catch (Exception e) {
            log.error(e);
            adicionarMensagemErro("msgReservaCriarError");
        }

        return RESERVA;
    }

    @Begin(flushMode = FlushModeType.MANUAL, join = true)
    public String alterarSetup() {
        operacaoAtual = Operacao.ALTERACAO;

        reserva = reservaSelecionada;

        hospedes = reservaHospedagemService.obterTodosHospedes();

        hospedeSelecionado = reserva.getHospede().getIdhospede();
        tipoApartamento = reserva.getApartamento().getTipoApartamento().getIdtipo();
        atualizarApartamentos();
        apartamentoSelecionado = reserva.getApartamento().getIdapart();
        buscarApartamento();

        return CADASTRO_ALTERAR;
    }

    @End
    public String alterar() {
        try {
            reservaHospedagemService.alterar(reserva, hospedeSelecionado, apartamentoSelecionado);

            adicionarMensagemInformacao("msgAlterarReservaSucesso");
            pesquisar();

            return RESERVA;
        } catch (Exception e) {
            log.error(e);

            adicionarMensagemErro("msgAlterarReservaError");
        }
        return RESERVA;
    }

    public String excluir() {
        reserva = reservaSelecionada;

        if (reserva.getReserva() == 0) {
            adicionarMensagemInformacao("msgExcluirOK");
            return null;

        } else if (reserva.getReserva() == 2) {
            adicionarMensagemInformacao("msgExcluirHospedao");
            return null;
        }
        try {
            reservaHospedagemService.excluir(reserva);
            adicionarMensagemInformacao("msgExcluirHospedagemCorreta");
            pesquisar();
        } catch (Exception e) {
            log.error(e);

            adicionarMensagemErro("msgExcluirHospedagemError");
        }
        return null;
    }

    @End
    public String cancelar() {
        if (operacaoAtual == Operacao.ALTERACAO || operacaoAtual == Operacao.DETALHAMENTO) {
            reservaHospedagemService.cancelar();
        }
        return RESERVA;
    }

    @End
    public void cancelarPagamento() {
    }

    @Begin
    public void gerarHospedagem() {
        reserva = reservaSelecionada;
        reserva.setDatachegada(new Date());
        Short hospeda = 2;
        reserva.setReserva(hospeda);

        hospedeSelecionado = reserva.getHospede().getIdhospede();
        apartamentoSelecionado = reserva.getApartamento().getIdapart();
    }

    @Begin
    public void gerarPagamentoSetup() {
        reserva = reservaSelecionada;
        reserva.setDatasaida(new Date());
        Short ok = 0;
        reserva.setReserva(ok);

        int dataCalcular = 0;
        dataCalcular = (int) diferencaEmDias(reserva.getDatachegada(), reserva.getDatasaida());


        if (dataCalcular > 0) {
            valor = reserva.getApartamento().getTipoApartamento().getValor() * dataCalcular;
        } else {
            valor = reserva.getApartamento().getTipoApartamento().getValor();
        }

        lancamento = new Lancamento();
        lancamento.setDatalancamento(new Date());
        lancamento.setValortotal(valor);
        lancamento.setFormapg("DINHEIRO");

    }

    @End
    public String gerarPagamento() {
        try {
            reservaHospedagemService.pagamento(lancamento, reserva);

            adicionarMensagemInformacao("msgReservaPagamentoSucesso");

            pesquisar();
        } catch (Exception e) {
            log.error(e);

            adicionarMensagemErro("msgReservaPagamentoError");
        }
        return null;
    }

    public static double diferencaEmDias(Date dataInicial, Date dataFinal) {
        double result = 0;
        long diferenca = dataFinal.getTime() - dataInicial.getTime();
        double diferencaEmDias = (diferenca / 1000) / 60 / 60 / 24; //resultado é diferença entre as datas em dias
        long horasRestantes = (diferenca / 1000) / 60 / 60 % 24; //calcula as horas restantes
        result = diferencaEmDias + (horasRestantes / 24d); //transforma as horas restantes em fração de dias

        return result;
    }

    public void pesquisar() {
        reservasDM = reservaHospedagemService.obterPorParametros(paramDataChegada, paramDataMarcacao, paramStatusReserva, paramTipoApartamento, paramHospede);
    }

    public void detalhar() {
        reserva = reservaSelecionada;
    }

    public void atualizarApartamentos() {
        apartamentos = reservaHospedagemService.obterApartamentosPorTipo(tipoApartamento);
    }

    public void buscarApartamento() {
        if (apartamentoSelecionado != null) {
            apartamento = reservaHospedagemService.obterApartamentoPorId(apartamentoSelecionado);
        }
    }


    //<editor-fold defaultstate="collapsed" desc="GETters e SETters">
    public Integer getHospedeSelecionado() {
        return hospedeSelecionado;
    }

    public void setHospedeSelecionado(Integer hospedeSelecionado) {
        this.hospedeSelecionado = hospedeSelecionado;
    }

    public Apartamento getApartamento() {
        return apartamento;
    }

    public void setApartamento(Apartamento apartamento) {
        this.apartamento = apartamento;
    }

    public Integer getApartamentoSelecionado() {
        return apartamentoSelecionado;
    }

    public void setApartamentoSelecionado(Integer apartamentoSelecionado) {
        this.apartamentoSelecionado = apartamentoSelecionado;
    }

    public List<TipoApartamento> getTiposApartamento() {
        return tiposApartamento;
    }

    public void setTiposApartamento(List<TipoApartamento> tiposApartamento) {
        this.tiposApartamento = tiposApartamento;
    }

    public Integer getTipoApartamento() {
        return tipoApartamento;
    }

    public void setTipoApartamento(Integer tipoApartamento) {
        this.tipoApartamento = tipoApartamento;
    }

    public List<Apartamento> getApartamentos() {
        return apartamentos;
    }

    public void setApartamentos(List<Apartamento> apartamentos) {
        this.apartamentos = apartamentos;
    }

    public ReservaEstadia getReserva() {
        return reserva;
    }

    public void setReserva(ReservaEstadia reserva) {
        this.reserva = reserva;
    }

    public List<Hospede> getHospedes() {
        return hospedes;
    }

    public void setHospedes(List<Hospede> hospedes) {
        this.hospedes = hospedes;
    }

    public Operacao getOperacaoAtual() {
        return operacaoAtual;
    }

    public void setOperacaoAtual(Operacao operacaoAtual) {
        this.operacaoAtual = operacaoAtual;
    }

    public Float getValor() {
        return valor;
    }

    public void setValor(Float valor) {
        this.valor = valor;
    }

    public Lancamento getLancamento() {
        return lancamento;
    }

    public void setLancamento(Lancamento lancamento) {
        this.lancamento = lancamento;
    }

    public Date getParamDataChegada() {
        return paramDataChegada;
    }

    public void setParamDataChegada(Date paramDataChegada) {
        this.paramDataChegada = paramDataChegada;
    }

    public Date getParamDataMarcacao() {
        return paramDataMarcacao;
    }

    public void setParamDataMarcacao(Date paramDataMarcacao) {
        this.paramDataMarcacao = paramDataMarcacao;
    }

    public Short getParamStatusReserva() {
        return paramStatusReserva;
    }

    public void setParamStatusReserva(Short paramStatusReserva) {
        this.paramStatusReserva = paramStatusReserva;
    }

    public Integer getParamTipoApartamento() {
        return paramTipoApartamento;
    }

    public void setParamTipoApartamento(Integer paramTipoApartamento) {
        this.paramTipoApartamento = paramTipoApartamento;
    }

    public String getParamHospede() {
        return paramHospede;
    }

    public void setParamHospede(String paramHospede) {
        this.paramHospede = paramHospede;
    }
    //</editor-fold>
}
